package org.hackystat.ui.chart.jfc.chartresource.dataset;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.jfree.data.time.Day;
import org.jfree.data.time.Month;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.Week;
import org.jfree.data.xy.XYSeries;

/**
 * Implements data factory.
 *
 * @author Pavel Senin.
 *
 */
public class DataFactoryImpl implements AbstractDataFactory {

  /**
   * {@inheritDoc}
   */
  public ArrayList<Point2D.Double> getData(String project, String sdtMajor, String sdtMinor,
      Date startDate, Date endDate, String granularity) {

    ArrayList<Point2D.Double> res = new ArrayList<Point2D.Double>();

    Integer intervalDays = this.calculateDifference(startDate, endDate);

    if ("dependency".equalsIgnoreCase(sdtMajor)) {
      Double k = Math.random() * 100D;

      for (Integer i = 0; i < intervalDays; i++) {
        Double rndY = Math.random() * k;
        res.add(new Point2D.Double(i.doubleValue(), rndY));
      }
      return res;
    }
    else if ("junit".equalsIgnoreCase(sdtMajor)) {
      return null;
    }
    else {
      return null;
    }
  }

  /**
   * Converts TelemetryXYdataset into JFC XYDataset.
   *
   * @param series the series to convert.
   * @param name the series name.
   * @return a sample dataset.
   */
  public XYSeries convertTelemetrySeries(TelemetryXYSeries series, String name) {
    final XYSeries series1 = new XYSeries(name);
    for (Double X : series.getSeriesData().keySet()) {
      series1.add(X, series.getSeriesData().get(X));
    }
    return series1;
  }

  /**
   * Reports interval in days for the given time frame.
   *
   * @param startDate start date;
   * @param endDate end date.
   * @return interval in days between end and start.
   */
  public Integer calculateDifference(Date startDate, Date endDate) {
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (startDate.compareTo(endDate) < 0) {
      earlier.setTime(startDate);
      later.setTime(endDate);
    }
    else {
      earlier.setTime(endDate);
      later.setTime(startDate);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR)) {
      tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
      difference += tempDifference;

      earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR)) {
      tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
      difference += tempDifference;

      earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
  }

  /**
   * @param project project to collect data from.
   * @param sdtMajor null.
   * @param sdtMinor null.
   * @param startDate starting date of the data interval.
   * @param endDate ending date of the data interval.
   * @param granularity data granularity (day, week, month: doesn't work really).
   * @return generated time series for plotting.
   */
  public TimeSeries getDataUnitTests(String project, String sdtMajor, String sdtMinor,
      Date startDate, Date endDate, String granularity) {

    TimeSeries series = null;

    /** dates difference. */
    Integer difference = calculateDifference(startDate, endDate);

    /** fixing calendars. */
    Calendar runningCalendar = Calendar.getInstance();
    runningCalendar.setTime(startDate);

    Calendar endCalendar = Calendar.getInstance();
    endCalendar.setTime(endDate);

    /** generating series. */
    if (difference < 15) {
      series = new TimeSeries("UnitTest-Success count <**>", Day.class);
      while (runningCalendar.before(endCalendar)) {
        Date date = runningCalendar.getTime();
        int num = (int) ((Math.random() - 0.5) * 10) + 10;
        series.add(new Day(date), num);
        runningCalendar.add(Calendar.DAY_OF_YEAR, 1);
      }
    }
    else if ((difference > 15) && (difference < 100)) {
      series = new TimeSeries("UnitTest-Success count <**>", Week.class);
      while (runningCalendar.before(endCalendar)) {
        Date date = runningCalendar.getTime();
        int num = (int) ((Math.random() - 0.5) * 10) + 10;
        series.add(new Week(date), num);
        runningCalendar.add(Calendar.WEEK_OF_YEAR, 1);
      }
    }
    else if (difference > 100) {
      series = new TimeSeries("UnitTest-Success count <**>", Month.class);
      while (runningCalendar.before(endCalendar)) {
        Date date = runningCalendar.getTime();
        int num = (int) ((Math.random() - 0.5) * 10) + 10;
        series.add(new Month(date), num);
        runningCalendar.add(Calendar.MONTH, 1);
      }
    }

    /** fixing title series. */
    if ("failure".equalsIgnoreCase(sdtMinor)) {
      series.setDescription("UnitTest-Failure count <**>");
    }

    return series;
  }
}
